package com.commons.util;

import com.aliyun.openservices.ClientConfiguration;
import com.aliyun.openservices.oss.OSSClient;
import com.aliyun.openservices.oss.model.OSSObject;
import com.aliyun.openservices.oss.model.ObjectMetadata;
import com.aliyun.openservices.oss.model.PutObjectResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author FCHEN
 */
public class OSSClientHelperImpl implements OSSClientHelper {

    private static Map<String,OSSClient> clientMaps = new HashMap<String,OSSClient>();

    private static ClientConfiguration clientConfiguration = null ;

    private String accessKeyId ;

    private String accessKeySecret ;

    public OSSClientHelperImpl(String accessKeyId , String accessKeySecret){
        this.accessKeyId = accessKeyId ;
        this.accessKeySecret = accessKeySecret ;
    }

    private OSSClient getClient (Constants.OssUploadAccessUri ossUploadAccessUri) {

        OSSClient client = clientMaps.get(String.valueOf(ossUploadAccessUri)) ;
        if (null == client) {
            client = new OSSClient(
                    String.valueOf(ossUploadAccessUri),
                    accessKeyId,
                    accessKeySecret,
                    clientConfiguration );
            clientMaps.put(String.valueOf(ossUploadAccessUri),client) ;
        }

        return  client ;
    }

    @Override
    public String postObject (File file,
                              Constants.OssUploadAccessFolder ossUploadAccessFolder) {

        String fileName = null ;
        String randomStringFileName = UUID.randomUUID().toString().replace("-","") ;
        InputStream inputStream = null;

        try {
            inputStream = new FileInputStream(file);

            String fileExtension = PathUtil.getExtension(file.getName()) ;
            if (StringUtils.isEmpty(fileExtension))  return "" ;

            fileName = postObject(inputStream
                    ,file.length()
                    ,randomStringFileName
                    ,ossUploadAccessFolder
                    ,Constants.OssUploadFileFormat
                    .getOssUploadFileFormat(fileExtension)) ;

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return fileName ;

    }

    @Override
    public String postObject (File file,
                              String randomStringFileName ,
                              Constants.OssUploadAccessFolder ossUploadAccessFolder) {

        String fileName = null ;
        InputStream inputStream = null;

        try {
            inputStream = new FileInputStream(file);

            String fileExtension = PathUtil.getExtension(file.getName()) ;
            if (StringUtils.isEmpty(fileExtension))  return "" ;

            fileName = postObject(inputStream
                    ,file.length()
                    ,randomStringFileName
                    ,ossUploadAccessFolder
                    ,Constants.OssUploadFileFormat
                    .getOssUploadFileFormat(fileExtension)) ;

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return fileName ;

    }

    @Override
    public String postObject (MultipartFile file,
                              Constants.OssUploadAccessFolder ossUploadAccessFolder) {

        InputStream inputStream = null ;
        String fileName = "" ;
        String randomStringFileName = UUID.randomUUID().toString().replace("-", "") ;
        try {
            inputStream = file.getInputStream() ;

            String fileExtension = PathUtil.getExtension(file.getOriginalFilename()) ;
            if (StringUtils.isEmpty(fileExtension))  return "" ;

            fileName = postObject(inputStream
                    ,file.getSize()
                    ,randomStringFileName
                    ,ossUploadAccessFolder
                    ,Constants.OssUploadFileFormat
                    .getOssUploadFileFormat(
                            fileExtension)) ;

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

        return fileName ;
    }

    @Override
    public String postObject (MultipartFile file,
                              String randomStringFileName ,
                              Constants.OssUploadAccessFolder ossUploadAccessFolder) {

        InputStream inputStream = null ;
        String fileName = "" ;
        try {
            inputStream = file.getInputStream() ;

            String fileExtension = PathUtil.getExtension(file.getOriginalFilename()) ;
            if (StringUtils.isEmpty(fileExtension))  return "" ;

            fileName = postObject(inputStream
                    ,file.getSize()
                    ,randomStringFileName
                    ,ossUploadAccessFolder
                    ,Constants.OssUploadFileFormat
                    .getOssUploadFileFormat(
                            fileExtension)) ;

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

        return fileName ;
    }

    @Override
    public String postObject (InputStream inputStream ,
                              Long fileSize ,
                              String randomStringFileName,
                              Constants.OssUploadAccessFolder ossUploadAccessFolder ,
                              Constants.OssUploadFileFormat ossUploadFileFormat ) {

        return postObject(inputStream,
                fileSize,
                randomStringFileName,
                Constants.OssUploadAccessUri.SHANGHAI,
                Constants.OssUploadAccessBucket.SHANGHAI,
                ossUploadAccessFolder,
                ossUploadFileFormat)  ;

    }

    @Override
    public String postObject (InputStream inputStream ,
                              Long fileSize ,
                              String randomStringFileName ,
                              Constants.OssUploadAccessUri    ossUploadAccessUri ,
                              Constants.OssUploadAccessBucket ossUploadAccessBucket ,
                              Constants.OssUploadAccessFolder ossUploadAccessFolder ,
                              Constants.OssUploadFileFormat ossUploadFileFormat ) {

        OSSClient client = getClient(ossUploadAccessUri) ;

        // 创建上传Object的Metadata
        ObjectMetadata meta = new ObjectMetadata();

        // 必须设置ContentLength
        meta.setContentLength(fileSize);

        // 文件名 例:Picture/Head/7805b8f0e0410c93510617b6ed94d8_M.jpg

        String fileName = "" ;
        String folders[] = ossUploadAccessFolder.toString().split("/") ;

        if (null != folders && folders.length == 2) {
            fileName =
                    ossUploadAccessFolder.toString().split("/")[0]
                            + "/" + ossUploadAccessFolder.toString().split("/")[1]
                            + "/" + randomStringFileName
                            + ossUploadFileFormat.toString() ;
        } else if (null != folders && folders.length == 3) {
            fileName =
                    ossUploadAccessFolder.toString().split("/")[0]
                            + "/" + ossUploadAccessFolder.toString().split("/")[1]
                            + "/" + randomStringFileName
                            + "_" + ossUploadAccessFolder.toString().split("/")[2]
                            + ossUploadFileFormat.toString() ;
        } else {
            return "" ;
        }

        // 上传Object.
        PutObjectResult result = client.putObject(
                ossUploadAccessBucket.toString(),
                fileName,
                inputStream, meta);

        return ossUploadAccessFolder.toString().split("/")[0]
                + "/" + ossUploadAccessFolder.toString().split("/")[1]
                + "/" + randomStringFileName + ossUploadFileFormat.toString() ;

    }

    @Override
    public OSSObject operateObject (Constants.OssFileAccessOperate ossFileAccessOperate , String uri) {

        return operateObject( Constants.OssUploadAccessUri.SHANGHAI ,
                Constants.OssUploadAccessBucket.SHANGHAI ,
                ossFileAccessOperate ,
                uri) ;

    }

    @Override
    public OSSObject operateObject (Constants.OssUploadAccessUri ossUploadAccessUri ,
                                    Constants.OssUploadAccessBucket ossUploadAccessBucket ,
                                    Constants.OssFileAccessOperate ossFileAccessOperate ,
                                    String uri) {

        // 初始化OSSClient
        OSSClient client = getClient(ossUploadAccessUri) ;

        OSSObject oSSObject = null ;

        if (ossFileAccessOperate.toString().equalsIgnoreCase(
                Constants.OssFileAccessOperate.DELETE.toString())) {
            client.deleteObject(ossUploadAccessBucket.toString(),uri) ;
        } else if (ossFileAccessOperate.toString().equalsIgnoreCase(
                Constants.OssFileAccessOperate.GET.toString())) {
            oSSObject = client.getObject(ossUploadAccessBucket.toString(),uri) ;
        }

        return oSSObject ;

    }

    static {

        clientConfiguration = new ClientConfiguration();

        clientConfiguration.setMaxConnections(Constants.OSS_UPLOAD_MAX_CONNECTIONS);
        clientConfiguration.setConnectionTimeout(Constants.OSS_UPLOAD_CONNECTION_TIMEOUT);
        clientConfiguration.setMaxErrorRetry(Constants.OSS_UPLOAD_MAX_ERROR_RETRY);
        clientConfiguration.setSocketTimeout(Constants.OSS_UPLOAD_SOCKET_TIMEOUT);

    }

}
